package com.tim.helper.fm;

import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.ReflectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 输出dubbo直调命令，末尾无分号
 *  https://cn.dubbo.apache.org/zh-cn/docsv2.7/user/references/telnet/
 */
public class DubboHelper {
    String hostPort = "";
    @Before
    public void init(){
        hostPort = "localhost:2181";   // local
//    hostPort = "10.1.56.164:2181";  // dev
//    hostPort = "10.1.52.164:2181";  // sit
//    hostPort = "10.1.48.164:2181";  // uat

    }

    @Test
    public void printDubboCMD() throws Exception {
        String info = "com.xqxc.api.impl.plat.marketing.activity.ActivityGoodsServiceImpl.getDefaultActivityInfo" +
                "";

        String classFullName, methodName, argClassFullName, argJson="";
        StringBuilder cmdBuilder = new StringBuilder();

        // 解析类全名、方法名
        info = info.trim();
        int index = info.indexOf("#");
        if(index>-1){
            classFullName = info.substring(0, index);
            methodName = info.substring(index+1);
        }else{
            index = info.lastIndexOf(".");
            classFullName = info.substring(0, index);
            methodName = info.substring(index+1);
        }

        // 反射获取类、方法；构建argJson参数
        try{
            Class<?> clazz = Class.forName(classFullName);
            Method[] methods = clazz.getMethods();
            for(Method method : methods){
                if(method.getName().equals(methodName)){
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    if(parameterTypes.length>0){
                        Class<?> parameterType = parameterTypes[0];
                        argClassFullName = parameterType.getName();
                        Object param = parameterType.newInstance();
                        argJson = JSON.toJSONString(param)
                                .replaceFirst("\\{", "{ \"class\":\""+argClassFullName+"\", ");
                    }
                }
            }
        }catch (ClassNotFoundException e){
            argJson = "{\"class\":\"\", }";
        }

        cmdBuilder.append("telnet "+hostPort)
                .append("\n")
                .append(String.format("invoke %s(%s)", info, argJson))
                .append("\n");
        System.out.println(cmdBuilder);
    }

    /*api配置： https://cn.dubbo.apache.org/zh-cn/docs/references/configuration/api/*/
    @Test
    public void invokeReference() throws Exception {
        Class<DubboHelper> clz = DubboHelper.class;
        String methodName="";
        Object[] args = new Object[0];
        // 当前应用配置
        ApplicationConfig application = new ApplicationConfig();
        application.setName("ltl-test");
        application.setQosEnable(false);

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://"+hostPort);

        // 注意：ReferenceConfig为重对象，内部封装了与注册中心的连接，以及与服务提供方的连接
        // 引用远程服务
        ReferenceConfig<DubboHelper> reference = new ReferenceConfig<>(); // 此实例很重，封装了与注册中心的连接以及与提供者的连接，请自行缓存，否则可能造成内存和连接泄漏
        reference.setApplication(application);
        reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
        reference.setInterface(clz);
        reference.setVersion("1.0.0");

        // 和本地bean一样使用demoService
        // 注意：此代理对象内部封装了所有通讯细节，对象较重，请缓存复用
        DubboHelper demoService = reference.get();
        Method method = clz.getMethod(methodName, clz);
        ReflectionUtils.invokeMethod(method, demoService, args);
    }

    @Test
    public void readZkProvider() throws Exception {
        String fullname = "com.fbank.core.fund.api.service.ifms.FinishStateService";

        String child = "/providers";
        ZooKeeper zooKeeper = new ZooKeeper(hostPort, 1000 * 10, System.out::println);
        List<String> children = zooKeeper.getChildren("/dubbo/"+fullname+child, false);
        System.out.println("SSSSSSSSSSSSSSSSSSSSSSSSS");
        children = children.stream().map(URLDecoder::decode).collect(Collectors.toList());
        System.out.println(children);
    }

    @Test// find . |grep Service；java文件夹列出接口路径，替换
    public void findServices(){
        String info = "";
        info = info.replaceAll("\\./java/", "")
                .replaceAll("/", ".")
                .replace(".java", "");
        System.out.println(info);
    }

    @Test
    public void readZkConsumers() throws Exception {
        String fullnames = "com.fbank.core.fund.api.service.ifms.FinishStateService";

        Map<String, List<String>> map = new HashMap<>();
        String child = "/consumers";
        ZooKeeper zooKeeper = new ZooKeeper( hostPort, 1000 * 10, System.out::println);
        for(String fullname : fullnames.trim().split("\n")){
            List<String> children = zooKeeper.getChildren("/dubbo/"+fullname+child, false);
            children = children.stream().map(URLDecoder::decode)
                    .map(e->{
                        return Arrays.stream(e.substring(e.indexOf('?')+1).split("&")).filter(item->item.startsWith("application")).findFirst().orElse("NONE").replace("application=",  "");
                    }).distinct()
                    .collect(Collectors.toList());

            System.out.println(children);
            map.put(fullname, children);
        }

        System.out.println("SSSSSSSSSSSSSSSSSSSSSSSSS");
        map.forEach((k,v)->System.out.println(k+""+v));

    }

    public void readZkProviders() throws Exception {
        String fullnames = "com.fbank.core.accountant.facade.service.flush.FlushService\n";

        Map<String, List<String>> map = new TreeMap<>();
        String child = "/providers";
        ZooKeeper zooKeeper = new ZooKeeper( hostPort, 1000 * 10, System.out::println);

        for(String fullname : fullnames.trim().split("\n")){
            List<String> children = zooKeeper.getChildren("/dubbo/"+fullname+child, false);
            children = children.stream().map(URLDecoder::decode)
                    .map(e->{
                        e = URLDecoder.decode(e.substring(0, e.indexOf('?')));
                        return e.substring(3, e.lastIndexOf("/"));
                    })
                    .distinct()
                    .collect(Collectors.toList());

            System.out.println(children);
            map.put(fullname, children);
        }

        System.out.println("SSSSSSSSSSSSSSSSSSSSSSSSS");
        map.forEach((k,v)->System.out.println(k+"="+v));
    }

}
